home *** CD-ROM | disk | FTP | other *** search
- /**************
- Program: POVSUDS.C (Use medium memory model)
- Usage: POVSUDS output.dat
- The screen will turn blue and the speaker will beep when the
- program has completed its full compliment of spheres.
-
- Basic algorithm from "Computers, Pattern, Chaos, and Beauty" by
- Clifford Pickover (St. Martin's Press).
- Program by Sam Hobbs, C User's Journal, Sept '91
-
- Purpose:
- Draws "osculating" tangent circles of random sizes in two dimensions.
- Outputs raytracer data in the form of user definable objects.
-
- Modification History:
- -----------------------
- 11/23/93 Eduard [esp] Schwan
- o Updated Dan's updates to support Macintosh models:
- o Uncluttered #ifdefs with IBMPC_DISPLAY & MAC_DISPLAY IDs
- o No-opped gotoxy for Mac
- o Added the write_pov_textures function
- o Removed commas from 1.0 object syntax output (write_pov_object)
- o Changed #define VERBOSE into command-line option be_verbose variable
-
- 11/20/93 Dan Farmer Version 2.0 (IBM version)
- o Converted to POV-Ray 2.0.
- o Made POV-Ray 2.0 the default ray tracer.
- o Put default ray tracer first on menu.
- o Dropped POV-Ray 0.5 support.
- o Reworked sample camera file.
- o Somewhere along the way, I added a color fill to the preview
- spheres (for the PC version only).
-
- 03/09/93 Eduard [esp] Schwan
- o Added code to support Macintosh implementation, more generic
- o Added minimal command-line parameter code
- o Added missing suds texture IDs, changed sudsNNN to sudsTexNNN for clarity
- o Cosmetics on source code, added function separators, made static.
- o Allocate humongo circle array dynamically, not as static array.
- o Fixed bug that left some spheres out in space, not touching.
- o Fixed syntax for POV 0.5, 1.0, 2.0.
- o Added user-configurable random distribution functions
-
- 01/16/93 dmf Add POV-Ray 1.5 support
- 01/05/92 Dan Farmer
- o Remove MAX_RADIUS_DIVISOR and replace with simple rmax value.
-
- 01/02/92 Tim Wegner
- o Changed to support new POV-Ray {} syntax
- o Added registerVGA call to link with egavga.obj
- o Made errors go to stderr
- o Added 3D support
- o Cleaned up input screen
- o Added multiple textures
- o Added spherical and rectangular bounding options
- o Output to command line parameter
- o Home the screen after <A>gain
- o Remove POV-Ray Noise and Turbulence variations
-
- 11/16/91 Dan Farmer
- o Added POV-Ray raytrace output.
- o (Uses printf() with redirection to create output include file.)
- o Track object extents and auto-center object.
- o Get user input for variable parameters.
- o Add z to circle_type structure. (Not used yet.)
- o Add POV Noise and Turbulence variations
- ****************/
-
-
- /*-----------------------------------------------------------------------*/
-
- #if defined (__TURBOC__) || defined (__BORLANDC__)
- #define IBMPC_DISPLAY 1
- #endif
-
- #if defined(applec) || defined(THINK_C)
- #define MAC_DISPLAY 1
- #endif
-
- /*==== ANSI C Library headers ====*/
- #include <stdlib.h> /* malloc, atof, etc. */
- #include <stdio.h>
- #include <string.h> /* strcat, etc. */
- #include <math.h>
- #include <time.h> /* required for random function */
-
- #if defined (IBMPC_DISPLAY)
- #include <conio.h>
- #include <graphics.h>
- #include <dos.h>
- #endif
-
- #if defined(MAC_DISPLAY)
- // if using Macintosh, include user interface stuff
- #include "POVSuds.mac.h"
- #else
- // This is usually a no-op for non-Mac Systems
- #define COOPERATE exit_if_kbhit();
- #endif
-
-
- /*-----------------------------------------------------------------------*/
-
- #define VERSION "2.0a"
-
- #if defined (IBMPC_DISPLAY)
-
- #define CIRCLE(x,y,r) circle(x,y,r)
-
- #define INIT_GRAPHICS() init_graphics()
- #define SETBKCOLOR(n) setbkcolor(n)
- #define CLOSEGRAPH() closegraph()
- #define RECTANGLE(x1,y1,x2,y2) rectangle(x1,y1,x2,y2)
- #define CLEARDEVICE() cleardevice()
- #define GOTO_XY(x,y) gotoxy(x,y)
- #else
- // Mac doesn't use these!
- #define CIRCLE(x,y,r)
- #define INIT_GRAPHICS()
- #define SETBKCOLOR(n)
- #define CLOSEGRAPH()
- #define RECTANGLE(x1,y1,x2,y2)
- #define CLEARDEVICE()
- #define GOTO_XY(x,y)
- #endif
-
- #if !defined(FALSE)
- #define FALSE 0
- #define TRUE !FALSE
- #endif
-
- #if defined (IBMPC_DISPLAY)
- #define RANDOMIZE() randomize()
- #define RAND() rand()
- // RAND_MAX is defined in the ANSI <stdlib.h>, hopefully Borland complies/compiles?
- // #define RAND_MAX 32767
- #else
- #if defined(applec) || defined(THINK_C)
- #define SEED() ((int)TickCount())
- #endif
- /* ANSI Standard random calls */
- #define RANDOMIZE() srand(SEED())
- #define RAND() rand()
- #endif
-
- #define RANDOM() DoDistribution()
-
- #if !defined(DBL)
- #define DBL double
- #endif
-
- #define MIN_RADIUS 0.01
- #define MAX_RADIUS 75.0 /* dmf: Scrap the MAX_RADIUS_DIVISOR */
- #define MIN_CIRCLES 1
- #define MAX_CIRCLES 5000 /* dmf: Increased max */
-
- #define OLD 1 /* Bounds style */
- #define BOX 2
- #define SPHERE 3
-
- #define POV20 1
- #define POV10 2
- #define RAY_MAX POV10
-
- #define DIST_EVEN 1
- #define DIST_GAUSS5 2
- #define DIST_GAUSS10 3
- #define DIST_MAX DIST_GAUSS10
-
-
- /*-----------------------------------------------------------------------*/
- int main(int argc, char *argv[]);
- static void generate_circles(void);
- static DBL new_radius(DBL x, DBL y, DBL z);
- static DBL distance(DBL x, DBL y, DBL z, int i);
- static void get_cmdline_args(int argc, char **argv);
- #if defined (IBMPC_DISPLAY)
- static void get_user_input(void);
- static void exit_if_kbhit(void);
- static void gerror(int errorcode);
- static void init_graphics(void);
- static void movetoxy(int x, int y);
- int sort_function( const void *a, const void *b);
- #endif
- static void write_pov_data(void);
- static void write_pov_object(DBL x, DBL y, DBL z, DBL r, int t);
- static void write_pov_sudsobj(void);
- static void write_pov_textures(int num_tex);
- static DBL GaussDistribution(int n);
- static DBL EvenDistribution(void);
- static DBL DoDistribution(void);
-
- #if !defined (min)
- static DBL min (DBL value1, DBL value2);
- static DBL max (DBL value1, DBL value2);
- DBL min(DBL value1, DBL value2)
- {
- return ( (value1 < value2) ? value1 : value2);
- }
- DBL max(DBL value1, DBL value2)
- {
- return ( (value1 > value2) ? value1 : value2);
- }
- #endif
-
-
- /*-----------------------------------------------------------------------*/
- typedef struct {
- DBL x;
- DBL y;
- DBL z;
- DBL r;
- } circle_type;
-
-
- /*-----------------------------------------------------------------------*/
- static circle_type *c = NULL;
- static int num_circles = 200;
- static DBL min_radius = MIN_RADIUS;
- static DBL max_radius = MAX_RADIUS;
- static short bailout_max = 12000;
- static int N;
- static int num_textures = 1;
- static int raytracer_kind = POV20;
- static int distMethod = DIST_EVEN;
- static DBL xmax, ymax; /* currently set to screen coordinates in get_user_input() */
- static DBL zmax = 0.0;
- static DBL rmax;
- static int constrain = OLD;
- static int be_verbose = FALSE;
- static FILE *fpout;
- static char *tracers[RAY_MAX] =
- {
- "POV-Ray v2.0",
- "POV-Ray v1.0"
- };
- static char *disttypes[DIST_MAX] =
- {
- "Even (Random) Distribution",
- "Gaussian Distribution, 5 samples",
- "Gaussian Distribution, 10 Samples"
- };
- static char *begComm[RAY_MAX] = {"//","//"}; // begin/end comments for each tracer syntax
- static char *endComm[RAY_MAX] = {"",""};
- static char *bounds[] =
- {
- "centers constrained to rectangular region",
- "objects constrained to rectangular region",
- "objects constrained to spherical region"
- };
- #define NUM_BOUNDS (sizeof(bounds)/sizeof(char *))
-
-
- /*-----------------------------------------------------------------------*/
- int main(int argc, char *argv[])
- {
- #if defined (IBMPC_DISPLAY)
- int keypress, done;
- #endif
-
- c = (circle_type *)malloc((MAX_CIRCLES+1)*sizeof(circle_type));
-
- #if defined (IBMPC_DISPLAY)
- if (argc != 2)
- {
- printf("\nPOV Suds\n Usage: POVSUDS <outfile>\n");
- exit(1);
- }
-
- if ((fpout = fopen(argv[1],"w")) == NULL)
- {
- printf("## Error! Can't open %s ... aborting\n",argv[1]);
- exit(1);
- }
-
- done = FALSE;
-
- INIT_GRAPHICS();
- do {
- SETBKCOLOR(0); /* color to black */
- CLEARDEVICE();
- get_user_input();
-
- CLEARDEVICE();
- generate_circles();
-
- // Redisplay in z sorted order, colored by r
- qsort( (void *)c, num_circles,sizeof(c[3]), sort_function);
- for (N = 0; N < num_circles; N++) {
- setfillstyle(SOLID_FILL, (int) c[N].r % getmaxcolor() +1);
- //pieslice(c[N].x, c[N].y, 0,360, c[N].r);
- fillellipse(c[N].x, c[N].y, c[N].r, c[N].r);
- }
-
-
- /* Frame the screen to show user that program is finished */
- GOTO_XY(1,3);
- fputs("\007", stdout); /* beep */
- fputs("<W>rite <Q>uit <R>edo",stdout);
- RECTANGLE(0, 0, getmaxx(), getmaxy()); /* draw frame */
-
- keypress = getch(); /* wait for keypress */
- switch (keypress)
- {
- case 'R':
- case 'r':
- done = FALSE;
- break;
- case 'W':
- case 'w':
- write_pov_data(); /* write PoV data */
- CLOSEGRAPH();
- return(0); /* quit */
- case 'Q':
- case 'q':
- done = TRUE;
- break;
- default:
- break;
- }
- } while (!done);
-
- CLOSEGRAPH();
- #else
- // The Mac way...
- get_cmdline_args(argc, argv);
- generate_circles();
- write_pov_data(); /* write PoV data */
- if ((fpout) && (fpout != stdout))
- fclose(fpout);
- #endif
-
- if (c != NULL)
- free(c);
- return 0;
- } // main
-
-
- /*-----------------------------------------------------------------------*/
- static void generate_circles()
- {
- DBL x_pos, y_pos, z_pos, radius;
- short bailout;
-
- RANDOMIZE();
-
- /* Note that xmax and ymax would probably be better for raytrace
- output if defined as a radius instead of screen rez. This would
- clump the circles into a larger circular area. */
-
- /* constrain to this sphere - tucked safely at the end of c[] */
- c[MAX_CIRCLES].x = xmax/2;
- c[MAX_CIRCLES].y = ymax/2;
- c[MAX_CIRCLES].z = zmax/2;
- c[MAX_CIRCLES].r = min(xmax,ymax) * 0.5;
-
- /* draw the rest of the circles */
- for (N = 0; N < num_circles ; N++)
- {
- bailout = 0;
- do {
- x_pos = RANDOM() * xmax;
- y_pos = RANDOM() * ymax;
- if(zmax > 0.0)
- z_pos = RANDOM() * zmax;
- else
- z_pos = 0.0;
- radius = new_radius(x_pos, y_pos, z_pos);
- if (bailout_max > 0)
- bailout++;
- if ((bailout & 31) == 31) // breathe every 32 times through
- COOPERATE
- } while ( ((radius < min_radius) || (radius > max_radius)) && (bailout < bailout_max) );
-
- if (bailout >= bailout_max)
- {
- printf("\nERROR! couldn't place circle #%d after %d tries... giving up.\n", N, bailout);
- num_circles = N; /* Set a new lower # circles! */
- break; /* out of for loop */
- }
- else
- {
- CIRCLE(x_pos,y_pos, radius);
-
- c[N].x = x_pos;
- c[N].y = y_pos;
- c[N].z = z_pos;
- c[N].r = radius;
- GOTO_XY(1,1);
- if(be_verbose)
- printf("%4d Units: sphere { <%7.3g, %7.3g, %7.3g>, %7.3g } \r",N,x_pos,y_pos,z_pos,radius);
- else
- printf("%4d Units\r",N);
- }
- }
- } // generate_circles
-
-
- /*-----------------------------------------------------------------------*/
- /* Function: new_radius(x,y,z)
- Purpose:
- Returns the distance from the point x,y,z to the nearest circle.
- Aborts and returns the calculated negative or zero distance if x,y
- lies on or inside of another circle
- */
-
- static DBL new_radius(DBL x, DBL y, DBL z)
- {
- int i, touched;
- DBL radius, dist_circle;
-
- radius = max_radius;
-
- switch (constrain)
- {
- case OLD:
- break;
-
- case BOX:
- /* don't let get outside box */
- if (radius > x)
- radius = x;
- if (radius > xmax - x)
- radius = xmax - x;
- if (radius > y)
- radius = y;
- if (radius > ymax - y)
- radius = ymax - y;
- if (zmax > min_radius*2)
- {
- if (radius > z)
- radius = z;
- if (radius > zmax-z)
- radius = zmax-z;
- }
- break;
-
- case SPHERE:
- dist_circle = distance(x,y,z,MAX_CIRCLES); /* dist pt to center */
- if (dist_circle >= 0)
- return 0.0; /* center ouside bounding sphere */
- else
- radius = min(radius, -dist_circle);
- break;
- }
-
- if (N == 0)
- touched = TRUE; // first one's always OK
- else
- for (i=0, touched=FALSE; i < N; i++)
- {
- dist_circle = distance(x, y, z, i);
- #if defined (IBMPC_DISPLAY)
- if(be_verbose) {
- GOTO_XY (1,2);
- printf("Test #%d\r",i);
- }
- GOTO_XY(1,3); printf(" \r"); // erase "Touched" message
- #endif
- // find smallest radius so far
- if (dist_circle <= radius)
- {
- radius = dist_circle;
- touched = TRUE; // yes, we bumped into another circle
- #if defined (IBMPC_DISPLAY)
- if(be_verbose) {
- GOTO_XY(1,3);
- printf("Touched\r");
- }
- #endif
- }
- // if we're too small, return
- if (radius < min_radius)
- return radius;
- }
-
- if (touched)
- return radius;
- else
- return 0.0; // if we didn't touch another circle, return as invalid
- } // new_radius
-
-
- /*-----------------------------------------------------------------------*/
- /* Function: distance(x,y,z,i)
- Purpose:
- Returns the distance from the point x,y,z to edge of circle i.
- Returns a negative value or zero distance if x,y is inside or on
- circle i.
- */
- static DBL distance(DBL x, DBL y, DBL z, int i)
- {
- DBL xdist, ydist, zdist, distancesq, dist;
- xdist = x - c[i].x;
- ydist = y - c[i].y;
- zdist = z - c[i].z;
- distancesq = (xdist*xdist) + (ydist*ydist) + (zdist*zdist);
- dist = sqrt(distancesq) - c[i].r;
- return (dist);
- } // distance
-
-
- /*-----------------------------------------------------------------------*/
- static void get_cmdline_args(int argc, char **argv)
- {
- int c;
- char filename[64];
-
- c = 1;
- fpout = stdout;
- while (c < argc)
- {
- if ((argv[c][0] == '-') || (argv[c][0] == '/'))
- {
- switch (argv[c][1])
- {
- case 'o': // -oOutputFileName
- case 'O':
- // get filename
- strcpy(filename,&argv[c][2]);
- // if no suffix, add one
- if (!strchr(filename,'.'))
- strcat(filename,".inc");
- if((fpout=fopen(filename,"w")) == NULL)
- {
- printf("Can't open %s ... aborting\n",filename);
- exit(1);
- }
- break;
-
- case 'n': // -nNumSpheres
- case 'N':
- num_circles = atoi(&argv[c][2]);
- if ((num_circles <= MIN_CIRCLES) || (num_circles > MAX_CIRCLES))
- num_circles = MIN_CIRCLES;
- break;
-
- case 'x': // -xXregionOfSpheres
- case 'X':
- xmax = atoi(&argv[c][2]);
- if ((xmax < 0.0) || (xmax > 999.0))
- xmax = 100.0;
- break;
-
- case 'y': // -yYregionOfSpheres
- case 'Y':
- ymax = atoi(&argv[c][2]);
- if ((ymax < 0.0) || (ymax > 999.0))
- ymax = 100.0;
- break;
-
- case 'z': // -zZregionOfSpheres
- case 'Z':
- zmax = atoi(&argv[c][2]);
- if ((zmax < 0.0) || (zmax > 999.0))
- zmax = 0.0;
- break;
-
- case 'r': // -rRayTracerType (1=PoV 2.0, 2=PoV 1.0)
- case 'R':
- raytracer_kind = atoi(&argv[c][2]);
- if ((raytracer_kind < 1) || (raytracer_kind > RAY_MAX))
- raytracer_kind = POV20;
- break;
-
- case 'a': // -aMinRadius
- case 'A':
- min_radius = atof(&argv[c][2]);
- if ((min_radius <= MIN_RADIUS) || (min_radius > 10.0))
- min_radius = MIN_RADIUS;
- break;
-
- case 'b': // -bMaxRadius
- case 'B':
- max_radius = atof(&argv[c][2]);
- if ((max_radius <= 1.0) || (max_radius > MAX_RADIUS))
- max_radius = MAX_RADIUS;
- break;
-
- case 'd': // -dDistMethod (1=even, 2=Gauss5, 3=Gauss10)
- case 'D':
- distMethod = atoi(&argv[c][2]);
- if ((distMethod < 1) || (distMethod > DIST_MAX))
- distMethod = DIST_EVEN;
- break;
-
- case 'k': // -kBoundingKind
- case 'K':
- constrain = atoi(&argv[c][2]);
- if ((constrain < 1) || (constrain > NUM_BOUNDS))
- constrain = 1;
- break;
-
- case 't': // -tNumTextures
- case 'T':
- num_textures = atoi(&argv[c][2]);
- if ((num_textures < 1) || (num_textures > 100))
- num_textures = 1;
- break;
-
- case 'v': // -v (Be Verbose)
- case 'V':
- be_verbose = TRUE;
- break;
-
- default:
- printf("Error! Unrecognized parameter '%s', ignored.\n",argv[c]);
- break;
- } // switch
- }
- else
- printf("Error! Unrecognized parameter '%s', ignored.\n",argv[c]);
-
- /* go to next parameter */
- c++; /* NOT! :-) [esp] */
- }
- } // get_cmdline_args
-
-
- #if defined (IBMPC_DISPLAY)
-
- /*-----------------------------------------------------------------------*/
- /*
- Get parameters from user.
- */
- static void get_user_input()
- {
- /* Get user input */
- /* Note that the ranges here are pretty much arbitrary values at this
- time. Need to test to establish good defaults and ranges. dmf */
- int i;
- char buf[200];
-
- /* center center boundaries to screen coordinates */
- xmax = getmaxx();
- ymax = getmaxy();
- movetoxy(0, 0);
- printf("\nPOV SUDS - Generate Osculating Objects\n\n");
- printf("Press <Return> to keep same values\n");
- printf("Current values shown in []\n");
-
- printf("\nEnter Ray Tracer\n");
- for (i=0; i<RAY_MAX; i++)
- printf("%-d=%s\n", i+1, tracers[i]);
- printf("Choice [%-d] : ", raytracer_kind);
- gets(buf);
- sscanf(buf,"%d->", &raytracer_kind);
- if(raytracer_kind==0) exit(0);
- if ((raytracer_kind < 1) || (raytracer_kind > RAY_MAX))
- raytracer_kind=POV20;
-
- printf("\nEnter Type of Bounds\n");
- for (i=0; i<NUM_BOUNDS; i++)
- printf("%-d=%s\n", i+1, bounds[i]);
- printf("Choice [%-d] : ",constrain);
- gets(buf);
- sscanf(buf,"%d->",&constrain);
- if ((constrain < 1) || (constrain > NUM_BOUNDS))
- constrain = OLD;
-
- printf("\nRegion Containing Spheres:\n");
- printf(" X from 0 to %-3g (fixed to screen resolution)\n",xmax);
- printf(" Y from 0 to %-3g (fixed to screen resolution)\n",ymax);
- printf(" Z from 0 to zmax (user set)\n");
- printf("Enter zmax (depth of region ) [%-g] : ",zmax);
- gets(buf);
- sscanf(buf,"%lf->",&zmax);
- if (zmax < 0)
- zmax = 0;
-
-
- CLEARDEVICE();
- movetoxy(0,0);
- printf("\nPOV SUDS - Generate Osculating Objects\n\n");
- printf("Press <Return> to keep same values\n");
- printf("Current values shown in []\n");
-
- printf("\nEnter Number Textures [%-d] : ",num_textures);
- gets(buf);
- sscanf(buf,"%d->",&num_textures);
- if (num_textures < 1)
- num_textures = 1;
-
- printf("\nEnter Max Spheres (%d-%d) [%-d] : ",
- MIN_CIRCLES, MAX_CIRCLES,num_circles);
- gets(buf);
- sscanf(buf,"%d",&num_circles);
- if (num_circles < MIN_CIRCLES)
- num_circles = MIN_CIRCLES;
- if (num_circles > MAX_CIRCLES)
- num_circles = MAX_CIRCLES;
-
- printf("\nEnter Min Radius (0.01-10) [%-7.4lf] : ",min_radius);
- gets(buf);
- sscanf(buf,"%lf",&min_radius);
- if (min_radius < MIN_RADIUS)
- min_radius = MIN_RADIUS;
- if (min_radius > 10.0)
- min_radius = 10.0;
-
- printf("\nEnter Max Radius (1-100) [%-4lf] : ",max_radius);
- gets(buf);
- sscanf(buf,"%lf",&max_radius);
- if (max_radius < min_radius)
- max_radius = min_radius;
- if (max_radius > MAX_RADIUS)
- max_radius = MAX_RADIUS;
-
- printf("\nEnter Distribution Type\n");
- for (i=0; i<DIST_MAX; i++)
- printf("%-d=%s\n", i+1, disttypes[i]);
- printf("Choice [%-d] : ", distMethod);
- gets(buf);
- sscanf(buf,"%d->", &distMethod);
- if ((distMethod < 1) || (distMethod > DIST_MAX))
- distMethod = DIST_EVEN;
-
- } // get_user_input
-
-
- /*-----------------------------------------------------------------------*/
- static void exit_if_kbhit()
- {
- if (kbhit())
- {
- getch();
- closegraph();
- exit(1);
- }
- } // exit_if_kbhit
-
-
- /*-----------------------------------------------------------------------*/
- static void gerror(int errorcode)
- {
- fprintf(stderr,"Graphics error: %s\n", grapherrormsg(errorcode));
- fprintf(stderr,"Press any key to halt.");
- getch();
- exit(1);
- } // gerror
-
-
- /*-----------------------------------------------------------------------*/
- /* Uses the Borland BGI drivers */
- static void init_graphics (void)
- {
- int gdriver = DETECT, gmode, errorcode;
-
- /* cut following 3 lines if you want to dynamically load egavga.bgi */
-
- errorcode = registerbgidriver(EGAVGA_driver);
- if (errorcode < 0)
- gerror(errorcode);
-
- initgraph(&gdriver, &gmode, "");
- errorcode = graphresult();
- if (errorcode != grOk)
- gerror(errorcode);
- } // init_graphics
-
-
- /*-----------------------------------------------------------------------*/
- #define VIDEO 0x10
- static void movetoxy(int x, int y)
- {
- union REGS regs;
- regs.h.ah = 2;
- regs.h.dh = y;
- regs.h.dl = x;
- regs.h.bh = 0;
- int86(VIDEO,®s,®s);
- } // movetoxy
-
-
- /*-----------------------------------------------------------------------*/
- //Sort function for qsort
- int sort_function( const void *a, const void *b)
- {
- if(a < b) return -1;
- if(a > b) return 1;
- return 0;
- } // sort_function
-
- #endif // IBMPC_DISPLAY
-
-
- /*-----------------------------------------------------------------------*/
- // Write an #include file for POV-Ray of a union of declared objects.
- // The composite is on the X/Y plane, left-handed coordinate system.
- // Uses a main datafile that defines "SudsObject" and associated textures
- // sudsTex1, sudsTex2...
- // Format:
- //
- // (POV 1.0)
- // #declare Suds = composite {
- // object { SudsObject scale <x y z> translate <x y z> texture { sudsTex1 } }
- // object { SudsObject scale <x y z> translate <x y z> texture { sudsTex2 } }
- // }
- //
- // (POV 2.0)
- // #declare Suds = union {
- // object { SudsObject scale <x, y, z> translate <x, y, z> texture { sudsTex1 } }
- // object { SudsObject scale <x, y, z> translate <x, y, z> texture { sudsTex2 } }
- // }
- //
- static void write_pov_data(void)
- {
- int i,t;
- DBL x_pos, y_pos, z_pos, radius;
- DBL x_len, y_len, z_len;
- DBL half_x, half_y, half_z;
- DBL x_center, y_center, z_center;
- DBL maxr_extent = 0.0;
- DBL maxx_extent = 0.0;
- DBL maxy_extent = 0.0;
- DBL maxz_extent = 0.0;
- DBL minr_extent = 1.7e+10;
- DBL minx_extent = 1.7e+10;
- DBL miny_extent = 1.7e+10;
- DBL minz_extent = 1.7e+10;
-
- /* Write header to file */
- fprintf(fpout,"%s File generated with POV-Suds Utility (version %s) %s\n",
- begComm[raytracer_kind-1], VERSION, endComm[raytracer_kind-1]);
-
- /* Write texture list to file */
- write_pov_textures(num_textures);
-
- /* Write SudsObject template to file */
- write_pov_sudsobj();
-
- /* Write the suds to file */
- switch(raytracer_kind)
- {
- case POV10:
- fprintf(fpout,"\n#declare Suds = composite {\n");
- break;
- case POV20:
- fprintf(fpout,"\n#declare Suds = union {\n");
- break;
- }
-
- /* Write out each of the objects */
- for (i=0; i<num_circles; i++)
- {
- x_pos = c[i].x;
- y_pos = c[i].y;
- z_pos = c[i].z;
- radius = c[i].r;
- t = i % num_textures; // roll through the textures...
-
- write_pov_object(x_pos, y_pos, z_pos, radius, t);
-
- /* keep track of the overall extents */
- maxx_extent = max(x_pos+radius, maxx_extent);
- maxy_extent = max(y_pos+radius, maxy_extent);
- maxz_extent = max(z_pos+radius, maxz_extent);
- maxr_extent = max(radius, maxr_extent);
-
- minx_extent = min(x_pos-radius, minx_extent);
- miny_extent = min(y_pos-radius, miny_extent);
- minz_extent = min(z_pos-radius, minz_extent);
- minr_extent = min(radius, minr_extent);
- }
-
- /* Center the composite object, based on extents */
- x_len = maxx_extent - minx_extent;
- y_len = maxy_extent - miny_extent;
- z_len = maxz_extent - minz_extent;
-
- half_x = x_len * 0.5;
- half_y = y_len * 0.5;
- half_z = z_len * 0.5;
-
- x_center = minx_extent + half_x;
- y_center = miny_extent + half_y;
- z_center = minz_extent + half_z;
-
- switch (raytracer_kind)
- {
- case POV10:
- fprintf(fpout," translate <%g %g %g> %s Center it\n",
- -x_center, -y_center, -z_center, begComm[raytracer_kind-1]);
- fprintf(fpout,"} %s Suds composite\n", begComm[raytracer_kind-1]);
- fprintf(fpout,"\n");
- fprintf(fpout,"#declare Suds_Bounding_Box = box { <-1 -1 -1> <1 1 1>\n");
- fprintf(fpout," scale <%g %g %g>\n", x_len, y_len, z_len);
- fprintf(fpout,"} %s Suds_Bounding_Box\n", begComm[raytracer_kind-1]);
- fprintf(fpout,"\n");
- break;
-
- case POV20:
- fprintf(fpout," translate <%g, %g, %g> %s Center it\n",
- -x_center, -y_center, -z_center, begComm[raytracer_kind-1]);
- fprintf(fpout,"%s NOTE: In POV-Ray 2.0, auto-bounded!\n", begComm[raytracer_kind-1]);
- fprintf(fpout,"} %s Suds union\n", begComm[raytracer_kind-1]);
- fprintf(fpout,"\n");
- break;
- }
-
- fprintf(fpout,"%s Object Extents: %s\n",
- begComm[raytracer_kind-1], endComm[raytracer_kind-1]);
-
- fprintf(fpout,"%s Min X = %7.2g, Y = %7.2g, Z = %7.2g, R = %7.2g %s\n",
- begComm[raytracer_kind-1], minx_extent, miny_extent, minz_extent, minr_extent, endComm[raytracer_kind-1]);
-
- fprintf(fpout,"%s Max X = %7.2g, Y = %7.2g, Z = %7.2g, R = %7.2g %s\n",
- begComm[raytracer_kind-1], maxx_extent, maxy_extent, maxz_extent, maxr_extent, endComm[raytracer_kind-1]);
-
- fprintf(fpout,"%s Objects generated : %5d %s\n",
- begComm[raytracer_kind-1], N, endComm[raytracer_kind-1]);
-
- fprintf(fpout,"%s Textures Needed : %5d %s\n",
- begComm[raytracer_kind-1], num_textures, endComm[raytracer_kind-1]);
-
- fprintf(fpout,"\n\n%s ------------------------------- %s\n",
- begComm[raytracer_kind-1], endComm[raytracer_kind-1]);
-
- fprintf(fpout,"%s POV SUDS settings used to generate this file %s\n\n",
- begComm[raytracer_kind-1], endComm[raytracer_kind-1]);
- fprintf(fpout,"%s Ray Tracer = %d (%s) %s\n",
- begComm[raytracer_kind-1], raytracer_kind,tracers[raytracer_kind-1], endComm[raytracer_kind-1]);
- fprintf(fpout,"%s Type of Bounds = %d (%s) %s\n",
- begComm[raytracer_kind-1], constrain,bounds[constrain-1], endComm[raytracer_kind-1]);
- fprintf(fpout,"%s Region Containing Objects:%s\n",
- begComm[raytracer_kind-1], endComm[raytracer_kind-1]);
- fprintf(fpout,"%s X from 0 to %7.2f (fixed to screen resolution) %s\n",
- begComm[raytracer_kind-1], xmax, endComm[raytracer_kind-1]);
- fprintf(fpout,"%s Y from 0 to %7.2f (fixed to screen resolution) %s\n",
- begComm[raytracer_kind-1], ymax, endComm[raytracer_kind-1]);
- fprintf(fpout,"%s Z from 0 to %7.2f (user setting of zmax) %s\n",
- begComm[raytracer_kind-1], zmax, endComm[raytracer_kind-1]);
- fprintf(fpout,"%s Number of Textures = %8d %s\n",
- begComm[raytracer_kind-1], num_textures, endComm[raytracer_kind-1]);
- fprintf(fpout,"%s Max Spheres = %8d %s\n",
- begComm[raytracer_kind-1], num_circles, endComm[raytracer_kind-1]);
- fprintf(fpout,"%s Min Radius = %8.4g %s\n",
- begComm[raytracer_kind-1], min_radius, endComm[raytracer_kind-1]);
- fprintf(fpout,"%s Max Radius = %8.4g %s\n",
- begComm[raytracer_kind-1], max_radius, endComm[raytracer_kind-1]);
- } // write_pov_data
-
-
- /*-----------------------------------------------------------------------*/
- /* Write a single circle out to PoV Ray format as a user-definable object */
- static void write_pov_object(DBL x, DBL y, DBL z, DBL r, int t)
- {
- DBL x_scale = r;
- DBL y_scale = x_scale;
- DBL z_scale = x_scale;
- DBL x_center = x;
- DBL y_center = y;
- DBL z_center = z;
-
- switch (raytracer_kind)
- {
- case POV10:
- fprintf(fpout,
- " object { SudsObject scale <%8.4g %8.4g %8.4g> translate <%8.4g %8.4g %8.4g> texture {sudsTex%-2d} }\n",
- x_scale, y_scale, z_scale, x_center, y_center, z_center, t+1);
- break;
-
- case POV20:
- fprintf(fpout,
- " object { SudsObject scale <%g, %g, %g> translate <%g, %g, %g> texture {sudsTex%-2d} }\n",
- x_scale, y_scale, z_scale, x_center, y_center, z_center, t+1);
- break;
- }
- } // write_pov_object
-
-
- /*-----------------------------------------------------------------------*/
- /* Write an example SudsObject in PoV Ray format */
- static void write_pov_sudsobj(void)
- {
- fprintf(fpout, "\n/* --- Example Suds Object Declaration --- */\n\n");
-
- switch (raytracer_kind)
- {
- case POV10:
- fprintf(fpout, "#declare SudsObject = object { sphere { <0 0 0> 1.0 } }\n");
- break;
-
- case POV20:
- fprintf(fpout, "#declare SudsObject = sphere { <0, 0, 0> 1.0 }\n");
- break;
- }
-
- fprintf(fpout, "\n/* --- end of Suds Object Declaration */\n");
-
- } // write_pov_sudsobj
-
-
- /*-----------------------------------------------------------------------*/
- /* Write a list of texture declarations in PoV Ray format */
- static void write_pov_textures(int num_tex)
- {
- int t;
-
- fprintf(fpout, "\n/* --- Example texture declarations, alter them to your liking --- */\n");
-
- for (t=1; t<=num_tex; t++)
- {
- fprintf(fpout, "\n");
- switch (raytracer_kind)
- {
- case POV10:
- fprintf(fpout, "#declare sudsTex%-2d = texture {\n", t);
- fprintf(fpout, " color red %g green %g blue %g\n", EvenDistribution(), EvenDistribution(), EvenDistribution());
- fprintf(fpout, " ambient 0.2 diffuse 0.7\n");
- fprintf(fpout, " specular 0.8 roughness 0.01\n");
- fprintf(fpout, "} // sudsTex%-2d\n", t);
- break;
-
- case POV20:
- fprintf(fpout, "#declare sudsTex%-2d = texture {\n", t);
- fprintf(fpout, " pigment {\n");
- fprintf(fpout, " color rgb <%g,%g,%g>\n", EvenDistribution(), EvenDistribution(), EvenDistribution());
- fprintf(fpout, " }\n");
- fprintf(fpout, " // normal { wrinkles, bumps, etc. }\n");
- fprintf(fpout, " finish {\n");
- fprintf(fpout, " ambient 0.2 diffuse 0.7\n");
- fprintf(fpout, " specular 0.8 roughness 0.01\n");
- fprintf(fpout, " }\n");
- fprintf(fpout, "} // sudsTex%-2d\n", t);
- break;
- }
- }
-
- fprintf(fpout, "\n/* --- end of texture declarations */\n");
-
- } // write_pov_textures
-
-
- /*-----------------------------------------------------------------------*/
- static DBL GaussDistribution(int n)
- {
- register int i;
- register DBL r = 0.0;
-
- // take n samples
- for (i=1; i <= n; i++) {
- r += (DBL)RAND();
- }
- // divide by n to get average
- r /= (DBL)n;
- // divide by max rand. # to get value between 0.0 and 1.0
- r /= (DBL)RAND_MAX;
- return (r);
- } // GaussDistribution
-
-
- /*-----------------------------------------------------------------------*/
- static DBL EvenDistribution(void)
- {
- register DBL r = 0.0;
-
- // divide by max rand. # to get value between 0.0 and 1.0
- r = (DBL)RAND() / (DBL)RAND_MAX;
- return (r);
- } // EvenDistribution
-
-
- /*-----------------------------------------------------------------------*/
- // Returns a number between 0 and 1.
- static DBL DoDistribution(void)
- {
- register DBL r = 0.0;
-
- switch (distMethod)
- {
- case DIST_EVEN:
- r = EvenDistribution();
- break;
- case DIST_GAUSS5:
- r = GaussDistribution(5);
- break;
- case DIST_GAUSS10:
- r = GaussDistribution(10);
- break;
- }
- return r;
- } // DoDistribution
-